﻿using Yitter.IdGenerator;

namespace Shop.Core.Helper
{
    public static class IdGenerater
    {
        /// <summary>
        /// 获取唯一Id，默认支持64个节点，每毫秒下的序列数6位。
        /// 在默认配置下，ID可用 71000 年不重复
        /// 在默认配置下，70年才到 js Number Max 值
        /// 默认情况下，500毫秒可以生成10W个号码。
        /// 如果需要提高速度，可以修改SeqBitLength长度。当SeqBitLength =10 ,100W个id约800毫秒。
        /// </summary>
        /// <returns>Id</returns>
        public static long GetNextId()
            => YitterSnowFlake.Instance.NextId();

        public class YitterSnowFlake
        {
            private static readonly Lazy<YitterSnowFlake> lazy = new Lazy<YitterSnowFlake>(() => new YitterSnowFlake());
            public static byte YitterWorkerIdBitLength { get { return 6; } }
            public static byte YitterSeqBitLength { get { return 6; } }
            public static ushort MaxWorkerId { get { return (ushort)(Math.Pow(2.0, YitterWorkerIdBitLength) - 1); } }

            private static short _currentWorkerId = 1;

            public static short CurrentWorkerId
            {
                get { return _currentWorkerId; }
                set
                {
                    if (value < 0 || value > MaxWorkerId)
                        throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", MaxWorkerId));
                    if (_currentWorkerId > -1)
                        throw new Exception(string.Format("worker Id can't be changed.{0}", _currentWorkerId));
                    else
                        _currentWorkerId = value;
                }
            }

            static YitterSnowFlake()
            {
            }

            private YitterSnowFlake()
            {
                if (_currentWorkerId > MaxWorkerId || _currentWorkerId < 0)
                    throw new Exception(string.Format("worker Id can't be greater than {0} or less than 0", MaxWorkerId));

                YitIdHelper.SetIdGenerator(new IdGeneratorOptions((ushort)_currentWorkerId)
                {
                    WorkerIdBitLength = YitterWorkerIdBitLength
                    ,
                    SeqBitLength = YitterSeqBitLength
                }); ;
            }

            public static YitterSnowFlake Instance
            {
                get
                {
                    return lazy.Value;
                }
            }

            public long NextId()
            {
                return YitIdHelper.NextId();
            }
        }
    }
}